package com.durian.base.net;

import androidx.collection.ArrayMap;
import android.text.TextUtils;

import com.durian.base.utils.LogUtils;
import com.durian.base.utils.StringUtils;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import okhttp3.FormBody;
import okhttp3.Headers;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;

/**
 * 说明：HttpRequestParams
 * <p/>
 * 作者：fanly
 * <p/>
 * 类型：Class
 * <p/>
 * 时间：2019/1/31 12:32
 * <p/>
 * 版本：version 1.0
 */
public class HttpRequestParams {

    private ArrayMap<String, String> mHeaders;
    private ArrayMap<String, Part>   mParams;
    private ArrayList<Part> mFiles;
    private RequestBody requestBody;
    private boolean     applicationJson;
    private boolean     urlEncoder;//是否进行URL编码
    private String      jsonParams;//json参数

    /**
     * Params
     **/

    public List<Part> getParams(){
        ArrayList<Part> parts = new ArrayList<>();
        if (mParams != null && !mParams.isEmpty()){
            for (Map.Entry<String, Part> entry:mParams.entrySet()){
                parts.add(entry.getValue());
            }
        }
        List<Part> commonParams = HttpConfig.get().getCommonParams();
        if (commonParams != null && !commonParams.isEmpty()){
            parts.addAll(commonParams);
        }
        return parts;
    }

    public HttpRequestParams putParams(String key, long value) {
        return putParams(key, String.valueOf(value));
    }

    public HttpRequestParams putParams(String key, int value) {
        return putParams(key, String.valueOf(value));
    }

    public HttpRequestParams putParams(String key, double value) {
        Double dou_obj = Double.valueOf(value);
        NumberFormat nf = NumberFormat.getInstance();
        nf.setGroupingUsed(false);
        return putParams(key, nf.format(dou_obj));
    }

    public HttpRequestParams putParams(String key, boolean value) {
        return putParams(key, String.valueOf(value));
    }

    public HttpRequestParams putParams(String key, String value) {
        if (!TextUtils.isEmpty(key) && value != null) {
            if (mParams == null) {
                mParams = new ArrayMap<>();
            }
            mParams.put(key, new Part(key, value));
        }
        return this;
    }

    public HttpRequestParams removeParams(String key){
        if (mParams != null && mParams.containsKey(key)){
            mParams.remove(key);
        }
        return this;
    }

    public HttpRequestParams putFile(String key,String filePath){
        if (StringUtils.isNotEmpty(filePath)){
            File file = new File(filePath);
            if (Utils.checkFile(file)){
                putFile(key,file);
            }
        }
        return this;
    }

    public HttpRequestParams putFile(String key, File file) {
        if (file == null || !file.exists() || file.length() == 0) {
            return this;
        }
        boolean isPng = Utils.isFileType(file, "png");
        if (isPng) {
            putFile(key, file, ContentType.PNG.getContentType());
            return this;
        }
        boolean isJpg = Utils.isFileType(file, "jpg");
        if (isJpg) {
            putFile(key, file, ContentType.JPEG.getContentType());
            return this;
        }
        if (!isPng && !isJpg) {
            putFile(key, new FileWrapper(file, null));
        }
        return this;
    }

    public HttpRequestParams removeFile(String key){
        if (mFiles != null && !mFiles.isEmpty()){
            ArrayList<Part> list = new ArrayList<>();
            for (Part part:mFiles){
                if (!StringUtils.isEquals(part.getKey(),key)){
                    list.add(part);
                }
            }
            mFiles.clear();
            mFiles.addAll(list);
        }
        return this;
    }

    private HttpRequestParams putFile(String key, FileWrapper fileWrapper) {
        if (!TextUtils.isEmpty(key) && fileWrapper != null) {
            File file = fileWrapper.getFile();
            if (Utils.checkFile(file)) {
                if (mFiles == null) {
                    mFiles = new ArrayList<>();
                }
                mFiles.add(new Part(key,fileWrapper));
            }
        }
        return this;
    }

    public HttpRequestParams putFile(String key, File file, String contentType) {
        if (Utils.checkFile(file)) {
            MediaType mediaType = null;
            try {
                mediaType = MediaType.parse(contentType);
            } catch (Exception e) {
                Utils.eLog(e);
            }
            putFile(key, new FileWrapper(file, mediaType));
        }
        return this;
    }

    public HttpRequestParams putFiles(String key, List<File> files){
        if (files != null){
            for (File file:files){
                if (Utils.checkFile(file)){
                    putFile(key,file);
                }
            }
        }
        return this;
    }

    public HttpRequestParams putFile(String key,List<String> files){
        if (StringUtils.isNotEmpty(key) && files != null && !files.isEmpty()){
            for (String path:files){
                putFile(key,path);
            }
        }
        return this;
    }

    /**Params**/

    /**
     * Header
     **/

    public HttpRequestParams putHeader(String key, int value) {
        return putHeader(key, String.valueOf(value));
    }

    public HttpRequestParams putHeader(String key, double value) {
        Double dou_obj = Double.valueOf(value);
        NumberFormat nf = NumberFormat.getInstance();
        nf.setGroupingUsed(false);
        return putHeader(key, nf.format(dou_obj));
    }

    public HttpRequestParams removeHeader(String key){
        if (mHeaders != null && mHeaders.containsKey(key)){
            mHeaders.remove(key);
        }
        return this;
    }

    public HttpRequestParams putHeader(String key, String value) {
        if (!TextUtils.isEmpty(key)) {
            if (mHeaders == null) {
                mHeaders = new ArrayMap<>();
            }
            if (!TextUtils.isEmpty(key) && !TextUtils.isEmpty(value)){
                mHeaders.put(key, value);
            }
        }
        return this;
    }

    public Headers getHeaders() {
        Headers.Builder builder = new Headers.Builder();
        builder.add("charset", "UTF-8");
        if (mHeaders != null) {
            for (Map.Entry<String, String> entry : mHeaders.entrySet()) {
                if (TextUtils.isEmpty(entry.getValue())) {
                    builder.add(entry.getKey());
                } else {
                    builder.add(entry.getKey(),entry.getValue());
                }
            }
        }
        /**
         * 添加公共headers
         */
        Headers commonHeaders = HttpConfig.get().getCommonHeaders();
        if (commonHeaders != null) {
            for (String name:commonHeaders.names()){
                builder.add(name,commonHeaders.get(name));
            }
        }
        return builder.build();
    }

    /**Header**/

    /**
     * 说明：URL编码，只对GET,DELETE,HEAD有效
     */
    public HttpRequestParams urlEncoder() {
        urlEncoder = true;
        return this;
    }

    public boolean isUrlEncoder() {
        return urlEncoder;
    }

    /**
     * 设置参数json格式
     * @return
     */
    public HttpRequestParams isApplicationJson(){
        applicationJson = true;
        return this;
    }

    public HttpRequestParams setJsonParams(String jsonParams) {
        this.applicationJson = true;
        this.jsonParams = jsonParams;
        return this;
    }

    public HttpRequestParams setRequestBody(RequestBody requestBody) {
        if (requestBody != null){
            this.requestBody = requestBody;
        }
        return this;
    }

    private RequestBody createFormBody(){
        FormBody.Builder builder = new FormBody.Builder();
        List<Part> commonParams = HttpConfig.get().getCommonParams();
        if (commonParams != null){
            for (Part part:commonParams){
                builder.add(part.getKey(),part.getValue());
            }
        }
        if (mParams != null && !mParams.isEmpty()){
            for (Map.Entry<String, Part> entry:mParams.entrySet()){
                builder.add(entry.getKey(),entry.getValue().getValue());
            }
        }
        return builder.build();
    }

    private RequestBody createFileReqeustBody(){
        MultipartBody.Builder builder = new MultipartBody.Builder();
        builder.setType(MultipartBody.FORM);
        List<Part> commonParams = HttpConfig.get().getCommonParams();
        if (commonParams != null){
            for (Part part:commonParams){
                builder.addFormDataPart(part.getKey(),part.getValue());
            }
        }
        if (mParams != null && !mParams.isEmpty()){
            for (Map.Entry<String, Part> entry:mParams.entrySet()){
                builder.addFormDataPart(entry.getKey(),entry.getValue().getValue());
            }
        }
        if (mFiles != null && !mFiles.isEmpty()){
            for (Part part:mFiles){
                FileWrapper fileWrapper = part.getFileWrapper();
                if (fileWrapper != null){
                    builder.addFormDataPart(part.getKey(), fileWrapper.getFileName(), RequestBody.create(fileWrapper.getMediaType(), fileWrapper.getFile()));
                }
            }
        }
        return builder.build();
    }

    private RequestBody createJsonRequestBody(){
        String json = "";
        if (jsonParams == null){
            JSONObject jsonObject = new JSONObject();
            List<Part> commonParams = HttpConfig.get().getCommonParams();
            if (commonParams != null){
                for (Part part:commonParams){
                    try {
                        jsonObject.put(part.getKey(),part.getValue());
                    }catch (JSONException e){
                        Utils.eLog(e);
                    }
                }
            }
            if (mParams != null && !mParams.isEmpty()){
                for (Map.Entry<String, Part> entry:mParams.entrySet()){
                    try {
                        jsonObject.put(entry.getKey(),entry.getValue().getValue());
                    }catch (JSONException e){
                        Utils.eLog(e);
                    }
                }
            }
            json = jsonObject.toString();
            if (HttpConfig.get().isDebug()){
                LogUtils.json(HttpConfig.Constant.TAG,json);
            }
        }else {
            try {
                json = new JSONObject(jsonParams).toString();
            }catch (JSONException e){
                Utils.eLog(e);
            }
        }
        return RequestBody.create(MediaType.parse(ContentType.JSON.getContentType()), json);
    }

    public RequestBody getRequestBody(){
        RequestBody body;
        if (applicationJson){
            body = createJsonRequestBody();
        }else if (requestBody != null){
            body = requestBody;
        }else if (mFiles != null && !mFiles.isEmpty()){
            return createFileReqeustBody();
        }else {
            return createFormBody();
        }
        return body;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        if (mHeaders != null && !mHeaders.isEmpty()){
            sb.append("请求Header")
                    .append("\n");
            for (Map.Entry<String,String> entry:mHeaders.entrySet()){
                sb.append(String.format("%s = %s",entry.getKey(),entry.getValue()))
                        .append("\n");
            }
        }
        if (mFiles != null && !mFiles.isEmpty()){
            sb.append("上传文件列表")
                    .append("\n");
            for (Part part:mFiles){
                sb.append(part.getFileWrapper().getFile())
                        .append("\n");
            }
        }
        if (mParams != null && !mParams.isEmpty()){
            sb.append("请求参数")
                    .append("\n");
            for (Map.Entry<String, Part> entry:mParams.entrySet()){
                sb.append(String.format("%s = %s",entry.getKey(),entry.getValue().getValue()))
                        .append("\n");
            }
        }
        return sb.toString();
    }
}
